--[[
任务模块业务逻辑总入口
接口列表：
sendTaskList		下发角色任务列表
taskCanAccept		判断任务是否可接
taskDoAccept		接任务
taskCanFinish		判断任务是否可交
taskDoFinish		交任务
taskCanAbandon		判断任务是否可放弃
taskDoAbandon		放弃任务
onLevelUp			角色升级回调 发送升级后可接任务
onBeforeMidNight	每天晚上11点回调 通知所有的玩家日常任务会在0点刷新
onMidNight			每天凌晨0点回调 重置日常任务周期 重置每日随机池任务
onUserLogin			用户登录 检查日常任务的完成周期是否超过

db中taskRecord的说明 taskID->taskInfo taskinfo包含下列字段
"status" 任务状态 未接 已接 已完成
"canFinish" 任务是否已满足可交条件 
[monsterID] 打怪数量 打怪任务中才有
[collectID] 采集数量 采集任务中才有

db中taskGroup的说明 groupID->groupInfo groupInfo 包含下列字段
"time"		 接或者交任务的时间
"finishNum"	 已经做完任务第几环
--]]

local Lang = require("common.Lang")
local Log = require("common.Log")
local LogDefine = require("common.LogDefine")
local ExcelNpcConf = require("excel.Npc")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local Map = require("core.Map")
local TaskDefine = require("task.Define")
local TaskAction = require("task.TaskAction")
local TaskHelp = require("task.TaskHelp")
local TaskGroup = require("task.TaskGroup")
local TaskCallbacks = require("task.TaskCallbacks")	
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local RoleDefine = require("role.RoleDefine")
local BountyLogic = require("task.BountyLogic")
local TaskHandler = require("task.HandlerL")
local TaskDailyStatus = require("task.TaskDailyStatus")
local FamilyBountyLogic = require("task.FamilyBountyLogic")
local RoleUIControl = require("role.RoleUIControl")
local RoleFFI = require("role.RoleFFI")
local Broadcast = require("broadcast.Broadcast")


function getTaskRecord(human, taskid)
  for i = 0, human.db.taskRecordLen - 1 do
      if human.db.taskRecord[i].taskid == taskid then
            return human.db.taskRecord[i]
      end  
  end
end

function delTaskRecord(human, taskid)
  for i = human.db.taskRecordLen -1, 0, -1 do
      if human.db.taskRecord[i].taskid == taskid then
          RoleFFI.copy_array_element(human.db.taskRecord , i, human.db.taskRecordLen -1, 'struct task_record')
          RoleFFI.memset_zero(human.db.taskRecord+(human.db.taskRecordLen-1), 'struct task_record')
          human.db.taskRecordLen = human.db.taskRecordLen -1
          break
      end  
  end
end

function getTaskGroupTask(human)
  for i = 0, human.db.taskRecordLen - 1 do
      local taskConfig = TaskHelp.getTaskConfig(human.db.taskRecord[i].taskid)
      if taskConfig and taskConfig.mainType == TaskDefine.TASK_TYPE_1_DAILY then
          return human.db.taskRecord[i]
      end  
  end
end

function delTaskGroupTask(human)
  for i = human.db.taskRecordLen -1, 0, -1 do
      local taskConfig = TaskHelp.getTaskConfig(human.db.taskRecord[i].taskid)
      if taskConfig and taskConfig.mainType == TaskDefine.TASK_TYPE_1_DAILY then
          RoleFFI.copy_array_element(human.db.taskRecord , i, human.db.taskRecordLen -1, 'struct task_record')
          RoleFFI.memset_zero(human.db.taskRecord+(human.db.taskRecordLen-1),'struct task_record')
          human.db.taskRecordLen = human.db.taskRecordLen -1
      end  
  end
end


-- 下发角色任务列表
function sendTaskList(human, flag)
	local msgRet = Msg.gc.GC_TASK_LIST
	msgRet.flag = flag
	
	-- 日常任务自动接取
	local flag, canDoGroupTask = TaskGroup.taskAutoAccept(human)
	
	-- 自动接取的任务
	autoAcceptTask(human)
	
	-- 获得角色的可接任务列表
	local canDoTasksLen, canDoTasks = TaskHelp.getCanDo(human)

	-- 获得角色的已接任务列表
	local doingTasksLen, doingTasks = TaskHelp.getDoing(human)
	
	if doingTasksLen > 16 then
	   doingTasksLen = 16
	end
	msgRet.doingTasks[0] = doingTasksLen
	for i = 1, doingTasksLen do
		local taskID = doingTasks[i]
		local taskNode = msgRet.doingTasks[i]
		TaskHelp.setTaskNode(taskNode, taskID, human)
	end
  
  if canDoTasksLen > 16 then
     canDoTasksLen = 16
  end
  if flag == 1 and canDoGroupTask then   --加入能做的日常任务
      if canDoTasksLen == 16 then
          canDoTasks[16] = canDoGroupTask
      else
          canDoTasksLen = canDoTasksLen + 1
          canDoTasks[canDoTasksLen] = canDoGroupTask
      end
  end
  
	msgRet.canDoTasks[0] = canDoTasksLen
	-- print("canDoTasksLen:", canDoTasksLen)
	for i = 1, canDoTasksLen do
		local taskID = canDoTasks[i]
		local taskNode = msgRet.canDoTasks[i]
		TaskHelp.setTaskNode(taskNode, taskID, human)
	end
	
	Msg.send(msgRet, human.fd)
	
	TaskDailyStatus.sendTaskDailyStatus(human)
end

-- 判断任务是否可接
function taskCanAccept(human, taskID)
	local record = getTaskRecord(human,taskID)
	if record and record.status == TaskDefine.TASK_ACCEPTED then
		return TaskDefine.TASK_ACCEPT_FAIL_ACCEPTED -- 任务不可接，已经接过
	end
	
	if record and record.status == TaskDefine.TASK_FINISHED then
		return TaskDefine.TASK_ACCEPT_FAIL_FINISHED -- 任务不可接，已经完成
	end 
	
	local taskConfig = TaskHelp.getTaskConfig(taskID)
	if not taskConfig then
		assert(nil, taskID)
	end

	if taskConfig.level and human.db.lv < taskConfig.level then
		return TaskDefine.TASK_ACCEPT_FAIL_LEVEL -- 任务不可接，等级不够
	end
	
	if taskConfig.prevTaskId then
		if taskConfig.mainType == TaskDefine.TASK_TYPE_1_MAIN then
			local maxMain = RoleUIControl.getMaxFinishMainTaskID(human)
			if maxMain < taskConfig.prevTaskId then 
				return TaskDefine.TASK_ACCEPT_FAIL_PREV_TASK -- 任务不可接，前置任务未完成 
			elseif maxMain > taskConfig.prevTaskId then
				return TaskDefine.TASK_ACCEPT_FAIL_ACCEPTED -- 任务不可接，已经接过
			end
		elseif taskConfig.prevTaskId ~= 0 then
		  local prevTaskRecord = getTaskRecord(human, taskConfig.prevTaskId)
			if prevTaskRecord == nil or prevTaskRecord.status ~= TaskDefine.TASK_FINISHED then
				return TaskDefine.TASK_ACCEPT_FAIL_PREV_TASK -- 任务不可接，前置任务未完成
			end
		end
	end
	
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY then -- 悬赏任务
		return BountyLogic.taskCanAccept(human, taskID, taskConfig)
	end
	
	return TaskDefine.TASK_ACCEPT_OK
end

-- 接任务
function taskDoAccept(human, taskID)
  local record = getTaskRecord(human, taskID)
  if record then
      assert()
  end
  if human.db.taskRecordLen >= 256 then
      asssert(nil, "taskRecordLen:"..human.db.taskRecordLen)
  end
  record = human.db.taskRecord[human.db.taskRecordLen]
  RoleFFI.memset_zero(human.db.taskRecord+human.db.taskRecordLen, 'struct task_record')
  
  record.taskid = taskID
  record.status = TaskDefine.TASK_ACCEPTED
	human.db.taskRecordLen = human.db.taskRecordLen +1
	
	local taskConfig = TaskHelp.getTaskConfig(taskID)
	
	TaskAction.playMovie(human, taskConfig.movie1)
	
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_MAIN then
		human.maxDoingMainTask = taskID
		RoleUIControl.sendFollowerNPCControl(human)-- 客户端虚拟跟随npc控制
	end
	
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY then -- 悬赏任务
		BountyLogic.taskDoAccept(human, taskID, taskConfig)
	end
	
	Log.write(Log.LOGID_OSS_TASK, human._id, human.account, human.name, human.db.lv, taskID, LogDefine.TASK_ACTION.ACCEPT)
end 

-- 判断任务是否可交
function taskCanFinish(human, taskID)
	-- 状态合法性判断
	local record = getTaskRecord(human, taskID)
	if record == nil or record.status ~= TaskDefine.TASK_ACCEPTED then
		return TaskDefine.TASK_FINISH_FAIL_NOT_ACCEPTED
	end
	
	local taskConfig = TaskHelp.getTaskConfig(taskID)
	
	-- 背包空间判断
	local rewardItemCount = TaskHelp.getRewardItem(taskID, taskConfig, human)
--  if TaskHelp.getChapterReward(taskConfig) then
--    rewardItemCount = rewardItemCount + 1  
--	end
	local bagFreeCount = BagLogic.getLeftGrids(human)
	if rewardItemCount > bagFreeCount then
		return TaskDefine.TASK_FINISH_FAIL_BAG
	end

	if record.finishFlag  == TaskDefine.TASK_FINISH_FLAG_NO_CHECK then
		return TaskDefine.TASK_FINISH_OK
	end

	-- 距离合法性判断
	if taskConfig.endNpcId ~= 0 and ExcelNpcConf.npc[taskConfig.endNpcId].exist_map == 1 then
		if ExcelNpcConf.npc[taskConfig.endNpcId].mapID ~= Map.scene_id_to_map_id[human.scene_id] then
			return TaskDefine.TASK_FINISH_FAIL_POS
		end
		
		--[[local len = Util.dist(human.x, human.y, ExcelNpcConf.npc[taskConfig.endNpcId].mapX, ExcelNpcConf.npc[taskConfig.endNpcId].mapY)
		if len > 500 then
			return TaskDefine.TASK_FINISH_FAIL_POS
		end--]]
	end 

	-- 目标合法性判断
	return TaskAction.isTaskActionFinish(human, taskID, taskConfig)
end

-- 交任务
function taskDoFinish(human, taskID)
	local taskConfig = TaskHelp.getTaskConfig(taskID)
	local record = getTaskRecord(human, taskID)
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY or taskConfig.mainType == TaskDefine.TASK_TYPE_1_FAMILYBOUNTY then -- 悬赏任务
		delTaskRecord(human, taskID)
	else
		record.status = TaskDefine.TASK_FINISHED
	end
	
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_MAIN then
		delTaskRecord(human, taskConfig.prevTaskId)
		human.maxFinishMainTask = taskID
		human.maxDoingMainTask  = nil
		RoleUIControl.sendFollowerNPCControl(human)				-- 客户端虚拟跟随npc控制        
	end
	
	--活跃度奖励
	
	-- 下发奖励
	local strReward = Lang.TASK_REWARD_GET
	local exp, worldExpAdd = TaskHelp.getRewardExp(taskConfig, human)
	
	local money = TaskHelp.getRewardMoney(taskConfig, human)
	if money > 0 then 
		strReward = strReward .. " " .. Lang.COMMON_YINLIANG .. " " .. money
		ObjHuman.addYinliang(human, money, "task_reward") 
		
		local msg = string.format("您获得了  %s*%d",Lang.COMMON_YINLIANG, money)
    Broadcast.sendBroadcast(human, Lang.CHAT, msg)
	end
	local zhangong = TaskHelp.getRewardZhangong(taskConfig, human)
	if zhangong > 0 then 
		strReward = strReward .. " " .. Lang.COMMON_ZHANGONG .. " " .. zhangong
		ObjHuman.addZhangong(human, zhangong, "task_reward")
		local msg = string.format("您获得了  %s*%d",Lang.COMMON_ZHANGONG, zhangong)
    Broadcast.sendBroadcast(human, Lang.CHAT, msg)
	end
	local weiwang = TaskHelp.getRewardWeiwang(taskConfig, human)
	if weiwang > 0 then
	  strReward = strReward.. " ".. Lang.COMMON_WEIWANG .." "..weiwang
	  ObjHuman.addPrestige(human, weiwang, "task_reward")
	  local msg = string.format("您获得了  %s*%d",Lang.COMMON_WEIWANG, weiwang)
    Broadcast.sendBroadcast(human, Lang.CHAT, msg)
	end
	local rongyu = TaskHelp.getRewardRongyu(taskConfig, human)
	if rongyu > 0 then
	  strReward = strReward.. " ".. Lang.COMMON_RONGYU .." "..rongyu
    ObjHuman.addRongyu(human, rongyu, "task_reward")
    local msg = string.format("您获得了  %s*%d",Lang.COMMON_RONGYU, rongyu)
    Broadcast.sendBroadcast(human, Lang.CHAT, msg)
	end
	
	local itemCount, itemGrids = TaskHelp.getRewardItem(taskID, taskConfig, human)
	for i = 1, itemCount do
		strReward = strReward .. " " .. Lang.COMMON_ITEM .. " " .. ItemDefine.getValue(itemGrids[i].id, "name")
		if ItemDefine.isEquip(itemGrids[i].id) then
			BagLogic.addItemByGrid(human, nil, itemGrids[i], "task_reward")
		else
			BagLogic.addItem(human, itemGrids[i].id, itemGrids[i].bind, itemGrids[i].cnt, "task_reward")
		end
	end
--	local chapterReward = TaskHelp.getChapterReward(taskConfig)
--	if chapterReward then  --章回奖励
--	   strReward = strReward .. " " .. Lang.COMMON_ITEM .. " " .. ItemDefine.getValue(chapterReward.id, "name")
--     if ItemDefine.isEquip(chapterReward.id) then
--        BagLogic.addItemByGrid(human, nil, chapterReward, "task_reward")
--     else
--        BagLogic.addItem(human, chapterReward.id, chapterReward.bind, chapterReward.cnt, "task_reward")
--     end
--	end
	
--	local familyContribution = TaskHelp.getRewardFamilyContribution(taskConfig, human)
--	if familyContribution > 0 then
--		FamilyLogicFL.updateFamilyContribution(human,familyContribution)
--		local family = FamilyManager.findByUuid(human.db.familyUuid)
--		if family then	
--			FamilyLogicFL.sendContribution(human,family)
--		end		
--	end
--	local familyExp = TaskHelp.getRewardFamilyExp(taskConfig, human)
--	if familyExp > 0 then
--		local family = FamilyManager.findByUuid(human.db.familyUuid)
--		if family then	
--			FamilyLogicFL.addFamilyExp(family,familyExp,true, human)
--		end			
--	end
	
  --自动接任务
  local autoAccept = autoAcceptTask(human)
  
	local msgRet = Msg.gc.GC_TASK_FINISH
	msgRet.taskID = taskID
	msgRet.retCode = 0
	msgRet.delTask = 1
	local canDoTasksLen, canDoTasks = TaskHelp.getCanDo(human)
	if canDoTasksLen > 16 then
	   canDoTasksLen = 16
	end
	msgRet.canDoTasks[0] = canDoTasksLen
	for i = 1, canDoTasksLen do
		local taskID = canDoTasks[i]
		local taskNode = msgRet.canDoTasks[i]
		TaskHelp.setTaskNode(taskNode, taskID, human)
	end
	Msg.send(msgRet, human.fd)

	TaskAction.playMovie(human, taskConfig.movie3)

	if taskConfig.groupId and taskConfig.groupId > 0 then -- 组任务
		TaskGroup.taskFinish(human, taskID, taskConfig)
	end

	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY then
		TaskCallbacks.taskInteractCB(human, TaskDefine.TASK_INTERACT_BOUNTY)
		BountyLogic.taskDoFinish(human, taskID,taskConfig)		
	end
	
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_FAMILYBOUNTY then
		FamilyBountyLogic.sendFamilyBountyList(human)
		FamilyBountyLogic.sendReward2Offer(human, taskConfig)
	end
	
	-- 任务奖励导致升级 重发taskList 冲掉了 客户端的task doinglist 所以要调整一下位置
	local levelUp = 0
	if exp > 0 then 
		strReward = strReward .. " " .. Lang.COMMON_EXP .. " " .. exp
		local preLv = human.db.lv
		local addExp = ObjHuman.addExp(human, exp, worldExpAdd,1)
		addExp = addExp or 0
		if taskConfig.autoComplete == 0 or taskConfig.autoComplete == nil then
			local msgAddExp = Msg.gc.GC_TASK_ADD_EXP			
			if preLv ~= human.db.lv then
				levelUp = 1
			end
			msgAddExp.levelUp = levelUp
			msgAddExp.exp = addExp --+ ObjHuman.getAttr(human, RoleDefine.EXP)
			msgAddExp.exp_max = ObjHuman.getAttr(human, RoleDefine.EXP_MAX)
			Msg.send(msgAddExp,human.fd)
		end
	end
		
	if autoAccept and levelUp == 0 then
	   TaskHelp.refreshDoing(human)  --刷新正在做的任务
	end
	Log.write(Log.LOGID_OSS_TASK, human._id, human.account, human.name, human.db.lv, taskID, LogDefine.TASK_ACTION.FINISH)
  


end

-- 判断任务是否可放弃
function taskCanAbandon(human, taskID)
  local record = getTaskRecord(human, taskID)
	if record == nil or record.status ~= TaskDefine.TASK_ACCEPTED then
		return TaskDefine.TASK_ABANDON_FAIL_NOT_ACCEPTED
	end
	
	local taskConfig = TaskHelp.getTaskConfig(taskID)
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_MAIN then
		return TaskDefine.TASK_ABANDON_FAIL_MAIN
	elseif taskConfig.mainType == TaskDefine.TASK_TYPE_1_DAILY then
		return TaskDefine.TASK_ABANDON_FAIL_DAILY
	end	
	return TaskDefine.TASK_ABANDON_OK
end

-- 放弃任务
function taskDoAbandon(human, taskID)
	delTaskRecord(human, taskID)	
	Log.write(Log.LOGID_OSS_TASK, human._id, human.account, human.name, human.db.lv, taskID, LogDefine.TASK_ACTION.ABANDON)
end

-- 自动接任务
function autoAcceptTask(human, canDoTasks, canDoTasksLen)
  if not canDoTasks then
      canDoTasksLen,canDoTasks = TaskHelp.getCanDo(human)
      if canDoTasksLen > 16 then
          canDoTasksLen = 16
      end
  end
  local msg ={taskID  = 0}
  local ret = nil
  for i = 1, canDoTasksLen do
      local config = TaskHelp.getTaskConfig(canDoTasks[i])
      if config.startNpcId == 0 then  
          msg.taskID = canDoTasks[i]
          TaskHandler.CG_TASK_ACCEPT(human, msg, true)
          ret = true
      end      
  end
  return ret
end

-- 角色升级回调 发送升级后可接任务(这里也有可能会删掉一些已经不可接的组循环任务)
function onLevelUp(human)
	sendTaskList(human, TaskDefine.TASK_LIST_FLUSH_LEVELUP)	
end

-- 每天晚上11点回调 通知所有的玩家日常任务会在4点刷新
function onBeforeMidNight()
	local msgNotify = Msg.gc.GC_BROADCAST
	msgNotify.type = Lang.CHAT
	msgNotify.msg = Lang.TASK_BEFORE_MID_NIGHT
	Msg.sendAll(msgNotify)
end

-- 每天凌晨0点回调 重置日常任务周期
function onMidNight()
	for uuid, human in pairs(ObjHuman.onlineUuid) do
    human.db.taskGroupCnt = 0
		sendTaskList(human, TaskDefine.TASK_LIST_FLUSH_MIDNIGHT)		
	end
	
	local msgNotify = Msg.gc.GC_BROADCAST
	msgNotify.type = Lang.CHAT
	msgNotify.msg = Lang.TASK_MID_NIGHT
	Msg.sendAll(msgNotify)
end

function updateDaily(human)
  BountyLogic.updateDaily(human)
  TaskGroup.updateDaily(human)
end

-- 检测主线任务的异常状态
function onUserMainTaskFix(human)
  for i = 0, human.db.taskRecordLen - 1 do
      local record = human.db.taskRecord[i]
      if record.status == TaskDefine.TASK_ACCEPTED and record.finishFlag ~= TaskDefine.TASK_FINISH_FLAG_CAN_FINISH then
            TaskCallbacks.loginFixMonsterTarget(human,record)
      end  
  end
	local taskDoingMaxID = RoleUIControl.getMaxDoingMainTaskID(human)
	if taskDoingMaxID == 0 then return end	
	local record = getTaskRecord(human, taskDoingMaxID)
	if record and record.status == TaskDefine.TASK_ACCEPTED and record.finishFlag == TaskDefine.TASK_FINISH_FLAG_CAN_FINISH then
	   local taskConfig = TaskHelp.getTaskConfig(taskDoingMaxID)
	   if taskConfig and taskConfig.mainType == TaskDefine.TASK_TYPE_1_MAIN and taskConfig.autoComplete == 1 then		
		    local msgTemp = {taskID = taskDoingMaxID}
		    TaskHandler.CG_TASK_FINISH(human, msgTemp)
	   end
	end
end

-- 场景AI触发一定会自动完成这个任务
function sceneFinishTask(human, taskID)
   local task = getTaskRecord(human, taskID)
   if task == nil or task.status ~= TaskDefine.TASK_ACCEPTED then
      return
   end
   task.finishFlag = TaskDefine.TASK_FINISH_FLAG_NO_CHECK
   taskDoFinish(human, taskID)
end